package tp.pr5;


import java.util.Scanner;

import tp.pr5.commands.Command;
import tp.pr5.commands.exceptions.CommandExecutionException;
import tp.pr5.commands.exceptions.WrongCommandFormatException;

public class Game extends tp.pr5.Observable<GameObserver>
{

	protected Map _mapa;
	protected Room _habitacionActual;

	protected Player _friki=new Player();
	protected boolean _exit;

	public void setCurrentRoom(Room currentRoom)
	{
		this._habitacionActual = currentRoom;
	}

	public Game(Map map)
	{
		try
		{
			this._mapa = map;
			this._habitacionActual = map.getCurrentRoom();
			//this._friki = new Player();
			this._exit = false;
		} catch (Exception e)
		{
			this._exit=true;
		}

	}

	public void setSalida(boolean exit)
	{
		this._exit = exit;
	}


	public Room getCurrentRoom()
	{
		return this._habitacionActual;
	}

/*	public Player getPlayer()
	{
		return this._friki;
	}

	public Map getCurrentMap()
	{
		return this._mapa;
	}*/

	public void runGame()
	{
		try
		{
			if (this._exit) throw new Exception();
			Scanner sc = new Scanner(System.in);
			showStatus();
			
			while (!_exit && !this._friki.dead())
			{
				System.out.print("> ");
				String line = sc.nextLine();
				try
				{
					Command auxCommand = Parser.parseCommand(line);
					auxCommand.execute();
				} catch (WrongCommandFormatException e)
				{
					System.out.print(MensajesConst.what);
				} catch (CommandExecutionException e)
				{
					System.out.print(e.getMessage());
				}

			}
		} catch (Exception e)
		{
			//System.out.println(e.getMessage());
		}

	}
	private void showStatus()
	{

		System.out.println(this._habitacionActual.getDescription()
				+ "\nHEALTH = " + String.valueOf((this._friki.getHealth()))
				+ ", SCORE =" + String.valueOf((this._friki.getPoints())));
	}
	public void requestQuit()
	{
		for (GameObserver gObs : this._observer)
			gObs.gameQuit();	
			this._exit = true;
	}
	public void	addGameObserver(GameObserver observer)
	{
		this.addObserver(observer);
	}
	//Registers a GameObserver to the model
	
	public void	addMapObserver(MapObserver observer)
	{
		this._mapa.addObserver(observer);
	}
	//Registers a MapObserver to the map contained in model
	
	public void	addPlayerObserver(PlayerObserver observer)
	{
		this._friki.addObserver(observer);
	}
	//Registers a PlayerObserver to the player contained in model
	
	public void	executeCommand(Command c)
	{
		c.configureContext(this,this._mapa, this._friki);
		try
		{
			c.execute();
			if (this._mapa.getCurrentRoom().isExit())
			{
				System.out.println("HEALTH = " +this._friki.getHealth()
						+ ", SCORE =" + this._friki.getPoints());
				
				for (GameObserver gObs : this._observer)
					gObs.gameOver(true);
			}
			
		} catch (CommandExecutionException e)
		{
			this.requestError(e.getMessage());
		}
	}
	//It executes a command and informs the observers whether the game has finished after executing the command.
	
	public boolean	isOver()
	{
		return this._exit;
	}
	//Checks if the game is finished
	
	public void	removeGameObserver(GameObserver observer)
	{
		this.removeGameObserver(observer);
	}
	//Removes a GameObserver attached to the model
	
	public void	removeMapObserver(MapObserver observer)
	{
		this._mapa.removeObserver(observer);
	}
	//Removes a MapObserver attached to the map contained in the model
	
	public void	removePlayerObserver(PlayerObserver observer)
	{
		this._friki.removeObserver(observer);
	}
	//Removes a PlayerObserver attached to the player contained in the model
	
	public void	requestError(java.lang.String msg)
	{
		for (GameObserver gObs : this._observer)
			gObs.gameError(msg);		
	}
	//Requests the game to inform the observers that an error has ocurred
	
	public void	requestHelp()
	{
		for (GameObserver gObs : this._observer)
			gObs.gameHelp();
	}
	//Requests the game to inform the observers about the help information
	
	public void	requestStart()
	{
		for (GameObserver gameObserverIterator : this._observer)
			gameObserverIterator.gameStart(getCurrentRoom(), this._friki.getPoints(), this._friki.getHealth());
	}
	//Requests the game to inform the observers that the game starts
	
public Map getCurrentMap() {
	return _mapa;
	
}
}